package com.example.aggregator;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.example.collector.RequestInfo;

public class Aggregator {

    public Map<String, RequestStat> aggregate(Map<String, ArrayList<RequestInfo>> requestDatas,  double durationInSection) {
        
        Map<String, RequestStat> requestStats = new HashMap<String, RequestStat>();
        for (Map.Entry<String, ArrayList<RequestInfo>> entry : requestDatas.entrySet()) {
            String apiName = entry.getKey();
            List<RequestInfo> requestInfos = entry.getValue();

            // 数据聚合计算
            RequestStat stat = this.doAggregate(requestInfos, durationInSection);

            requestStats.put(apiName, stat);
        }

        return requestStats;
    }

    public RequestStat doAggregate(List<RequestInfo> requestInfos,  double durationInSection) {

        RequestStat stat = new RequestStat();

        // 数据计算
        double minRespTime = Double.MAX_VALUE;
        double maxRespTime = Double.MIN_VALUE;
        double sumRespTime = 0;
        double avgRespTime = 0;
        double tps = 0;
        double p99RespTime = 0;
        double p999RespTime = 0;

        for (RequestInfo requestInfo : requestInfos) {
            if (requestInfo.getRespTime() < minRespTime) {
                minRespTime = requestInfo.getRespTime();
            }
            if (requestInfo.getRespTime() > maxRespTime) {
                maxRespTime = requestInfo.getRespTime();
            }
            sumRespTime += requestInfo.getRespTime();
        }

        avgRespTime = sumRespTime / requestInfos.size();
        tps = requestInfos.size() / durationInSection;

        requestInfos.sort(new Comparator<RequestInfo>() {
            @Override
            public int compare(RequestInfo o1, RequestInfo o2) {
                return (int) (o1.getRespTime() - o2.getRespTime());
            }
        });

        p99RespTime = percentile(requestInfos, 0.99);
        p999RespTime = percentile(requestInfos, 0.999);

        stat.setAvgRespTime(avgRespTime);
        stat.setMaxRespTime(maxRespTime);
        stat.setMinRespTime(minRespTime);
        stat.setP99RespTime(p99RespTime);
        stat.setP999RespTime(p999RespTime);
        stat.setTps(tps);
        stat.setCount(requestInfos.size());

        return stat;
    }

    private double percentile(List<RequestInfo> requestInfos, double d) {
        int n = (int) (requestInfos.size() * d);
        return requestInfos.get(n).getRespTime();
    }
}
